from django.shortcuts import render
from itsdangerous import serializer
from rest_framework import viewsets
from rest_framework.generics import GenericAPIView
from rest_framework.mixins import ListModelMixin, RetrieveModelMixin, CreateModelMixin, UpdateModelMixin, \
    DestroyModelMixin
from rest_framework.response import Response
from rest_framework.serializers import Serializer
# Create your views here.
from rest_framework.views import APIView

from api.models import Employee
from .BaseAuthentication import MyAuth
from .Permission import MyPermission
from .Simplie import MySimple
from .response import APIResponse

from .serializers import EmpSerializer, DeEmpSerializer, ModelSer, DeModelSer  # 导入自定义的序列化类


# 使用原生的drf语句写的,其中有封装的response
class EmployeeAVIView(APIView):
    def get(self, request, *args, **kwargs):
        id = kwargs.get('id')
        print('这是api中获取到的id')
        print(id)
        if id:
            try:
                one_id = Employee.objects.filter(id=id)[0]
                # 查询到的数据无法直接序列化,需要使用序列化类来完成序列化( 我们上面定义的序列化类导入一下 )
                # one_id=EmpSerializer(one_id).data
                one_id = ModelSer(one_id).data
                # return Response({
                #     "status":200,
                #     "msg":"查询单个数据成功",
                #     "result":one_id
                # })
                # 下面是使用封装的response的写法
                return APIResponse(results=one_id)

            except:
                return Response({
                    "status": 500,
                    "msg": "查询单个数据失败",
                })
        else:
            # 查询所有
            all_id = Employee.objects.all()
            # 使用序列化器完成多个员工的序列化,需要制定many=True
            # all_id=EmpSerializer(all_id,many=True).data   #使用Serializer的查询
            all_id = ModelSer(all_id, many=True).data  # 使用ModelSerializer查询
            # return Response({
            #     "status": 200,
            #     "msg": "查询全部数据成功",
            #     "result":list(all_id)
            # })
            # 下面是使用封装的response的写法
            return APIResponse(results=all_id)

    # 新增单个和多个
    def post(self, request, *args, **kwargs):
        user = request.data
        print(user)
        if isinstance(user, dict):
            # 符合表示添加一个对象,表示添加一个对象
            many = False
        elif isinstance(user, list):
            # 是列表时,表示添加多个对象
            many = True
        else:
            # 表示输入有误
            return Response({
                "status": 500,
                "message": "输入有误,请重新输入",

            })

        # 使用序列乎其对前台提交的数据进行反序列化
        # 在反序列化的时候需要制定关键字参数data
        try:
            post_user = DeEmpSerializer(data=user, many=many)

            # 使用is_valid()对序列化的数据进行校验,校验合法返回True
            print(post_user.is_valid())
            if post_user.is_valid():
                post_save = post_user.save()  # 进行存储
                # 调用save()去存储对象必须重写create方法
                return Response({
                    "status": 200,
                    "message": "存储成功",
                    "result": EmpSerializer(post_save, many=many).data
                })
            return Response({
                "status": 500,
                "message": "存储失败",
                # 错误信息包含在errors里面,会出现提示信息
                "result": post_user.errors
            })
        except:
            return Response({'指令有误,数据回滚'})

    # 删除单个和多个,删除和新增,修改等对数据进行操作是必须添加try捕获,进行数据的一致性保障
    def delete(self, request, *args, **kwargs):
        # 2选一,看数据在哪写,都可以
        id = kwargs.get('id')
        ids = request.data.get('ids')

        if id or ids:

            # 此时需要考虑,空对象没有len属性,还需要进一步判断
            if len(ids) != 1:  # 长度不是1,则是删除多个
                # 先判断表里面有没有用户输入的id对应的值,有则删除,无则返回错误
                for i in ids:
                    try:
                        print('这是删除多个的')
                        # 将删除的数据添加到一个新列表中(在删除之前收集数据),用来展示在删除结果之中
                        list1 = []
                        ress = Employee.objects.filter(id=i)[0]
                        list1.append(ress)
                        # list2 = ModelSer(list1, many=True).data
                        list2 = ModelSer(ress).data
                        # 删除了多个成功,但是显示的列表的时候list2里面只有初识添加的,未解决

                        print('删除正确的时候')
                        res = Employee.objects.filter(id=i)[0].delete()
                        return Response({
                            "status": 200,
                            "message": "删除多个成功,但显示只显示了删除的第一个,待修改",
                            "result": list2
                        })
                    except:
                        print('查无此号')
                        return ({
                            "status": 500,
                            "message": "数据传输正确,但是查无此号"
                        })
                # print(list2)
                # return Response({
                #         "status":200,
                #         "message":"删除多个成功,但显示只显示了删除的而第一个,待修改",
                #         "result":list2
                # })
            elif len(ids) == 1:  # 否则删除单个,暂时不考虑以哪个数据为主(目前以ids为主)
                print(ids)
                for i in ids:
                    print(i)
                    # 如果查无此号,126行直接报错,执行except模块
                    try:
                        ress = Employee.objects.filter(id=i)[0]
                        list3 = ModelSer(ress).data
                        # 如果有此号,则删除,没有表示查无此号
                        ress.delete()
                        print(i, ress)
                        return Response({
                            "status": 200,
                            "message": "删除一个正确",
                            "result": list3
                        })
                    except:
                        return Response({
                            "status": 500,
                            "message": "删除单个,查无此号"
                        })


            else:  # 数据有误
                return Response({
                    "status": 500,
                    "message": "输入的数字格式有误,请重新输入"
                })
        else:
            return Response({
                "status": 500,
                "message": "输入错误,请重新输入你要删除的id"
            })

    # 修改一个数据中的单个和多个
    def put(self, request, *args, **kwargs):
        up_data = request.data
        up_id = kwargs.get('id')
        try:
            up_obj = Employee.objects.filter(id=up_id)[0]
        except:
            return Response({
                "status": 500,
                "message": "修改时,查无此信息"
            })
        # 修改时需要制定instance参数,制定你要修改的是哪一个对象,前者是需要修改成的,后者是待修改的
        up_ser = DeModelSer(data=up_data, instance=up_obj)
        up_ser.is_valid(raise_exception=True)
        up_ser.save()
        return Response({
            "status": 200,
            "message": "更新成功",
            "result": ModelSer(up_obj).data
        })

    # 修改多个对象
    def patch(self, request, *args, **kwargs):
        res_data = request.data
        id = kwargs.get('id')
        if id and isinstance(res_data, dict):
            dis = [id]
            res_data = [res_data]

        elif not id and isinstance(res_data, list):
            ids = []
            for dic in res_data:
                pk = dic.pop('pk', None)
                if pk:
                    ids.append(pk)
                else:
                    return Response({
                        "status": 400,
                        "message": "pk不存在",
                    })
        else:
            return Response({
                "status": 200,
                "message": "数据格式传输有误"
            })
        user_list = []
        new_list = []
        for index, pk in enumerate(ids):
            try:
                user_obj = Employee.objects.get(pk=pk)
                user_list.append(user_obj)
                new_list.append(res_data[index])
            except:
                continue
        # 通过contenxt可以将view里的参数传递给序列化器
        user_ser = DeModelSer(data=new_list, instance=user_list, partial=True, many=True, context={"request": request})
        user_ser.is_valid()
        user_ser.save()
        return Response({
            "status": 200,
            "message": "修改成功"
        })


# 使用GenericAPIView重新写查询操作
 ################3
    #有一个问题,queryset定义在外面,只能确定一个值,定义在里面又有问题(暂定)
    ###############3
class EmployeeGenericAPIView(GenericAPIView):
    # 获取当前视图所操作的模型,与序列化器类
    queryset = Employee.objects.all()
    ################3
    #有一个问题,queryset定义在外面,只能确定一个值,定义在里面又有问题(暂定)
    ###############3
    serializer_class = ModelSer
    def get(self, request, *args, **kwargs):
        id = kwargs.get('id')
        print('这是api中获取到的id')
        print(id)
        # serializer_class=ModelSer
        # lookup_field='id'

        if id:
            try:
                # one_id = Employee.objects.filter(id=id)[0]
                #下面是使用GenericAPIView方式书写的,里面自动书写了get方法,可以直接使用
                ####要使用必须有queryset属性
                # queryset=Employee.objects.filter(id=id)[0]
                print('单个查询上')
                one_id=self.get_queryset()
                # one_id = ModelSer(one_id).data
                #下面是使用GenericAPIView方式书写的,也是写了序列化器类
                print('单个查询中')
                one_id=self.get_serializer(one_id).data
                print('单个查询')

                return APIResponse(results=one_id)

            except:
                return Response({
                    "status": 500,
                    "msg": "查询单个数据失败",
                })
        else:
            # 查询所有
            # all_id = Employee.objects.all()
            #想使用必须有一个queryset属性,重要,必须必须
            # queryset=Employee.objects.all()
            print('整体上')
            all_id = self.get_queryset()
            print('整体中')
            # all_id = ModelSer(all_id, many=True).data  # 使用ModelSerializer查询
            all_id=self.get_serializer(all_id,many=True).data
            print('整体下')
            return APIResponse(results=all_id)

#使用mixins的五大工具视图
class MixinsAPIView(ListModelMixin,     #提供了查询的所有方法
                    RetrieveModelMixin, #查询单个
                    CreateModelMixin,   #创建对象
                    UpdateModelMixin,   #更新单个,局部,整体
                    DestroyModelMixin,  #删除单个
                    GenericAPIView):    #工具视图
    queryset = Employee.objects.all()
    serializer_class = ModelSer
    #查询单个和多个
    def get(self, request, *args, **kwargs):
        if 'pk' in kwargs:
            return self.retrieve(request,*args, **kwargs)  #查询单个
        else:
            return self.list(request,*args, **kwargs)      #查询所有

    #新增单个或多个
    def post(self, request, *args, **kwargs):
        response=self.create(request,*args, **kwargs)
        return APIResponse(results=response.data)

    #单整体改
    def put(self,request, *args, **kwargs):
        response=self.update(request,*args, **kwargs)
        return APIResponse(results=response.data)

    #单局部改
    def patch(self,request, *args, **kwargs):
        response=self.partial_update(request,*args, **kwargs)
        return APIResponse(results=response.data)

    #删除
    def delete(self,request, *args, **kwargs):
        self.destroy(request,*args, **kwargs)
        return APIResponse('删除成功')

#使用视图集viewsets进行操作
class ViewsetsAPIView(viewsets.ModelViewSet):
    queryset = Employee.objects.all()
    serializer_class = ModelSer

    def login(self,request, *args, **kwargs):
        return self.retrieve(request, *args, **kwargs)
    def count(self,request, *args, **kwargs):
        return  self.list(request, *args, **kwargs)

#使用视图集合完成登录注册
class Sets(viewsets.ModelViewSet):
    queryset = Employee.objects.all()
    serializer_class = ModelSer

    def login(self,request, *args, **kwargs):
        return Response({
            "status":200,
            "message":"恭喜你,登录成功"
        })
    def register(self,request, *args, **kwargs):
        return Response({
            "status": 200,
            "message": "恭喜你,注册账号成功"
        })

#自定义三大权限认证器

#1,自定义--认证器类
class Myauth(APIView):
    authentication_classes = [MyAuth]
    def get(self,request,*args,**kwargs):
        #认证通过进行用户的查询
        user=Employee.objects.first()
        return APIResponse('认证成功')

#2,自定义--权限类
class Permission(APIView):
    # 有问题
    # authentication_classes = [MyPermission]
    def get(self,request,*args,**kwargs):
        user = Employee.objects.first()
        return APIResponse('权限认证通过')

#,自定义--频率类
class SimplieAPIView(APIView):
    throttle_classes = [MySimple]
    def get(self,request,*args,**kwargs):
        return APIResponse("读操作成功")
    def post(self,request,*args,**kwargs):
        return APIResponse("写操作成功")
